package postgres

import (
	"context"
	"github.com/jackc/pgx/v5"
	"ozonTest/internal/domain/comments/model"
	model2 "ozonTest/internal/domain/posts/model"
	"testing"
	"time"
)

func setupTestDB(t *testing.T) *pgx.Conn {
	conn, err := pgx.Connect(context.Background(), "postgres://postgres:ЕРАВЕСОМЕПВД@localhost:5432/postgres")
	if err != nil {
		t.Fatalf("Unable to connect to database: %v\n", err)
	}

	_, err = conn.Exec(context.Background(), `
		DROP TABLE IF EXISTS comments;
		DROP TABLE IF EXISTS posts;
		CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT NOT NULL,
    comments_enabled BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE comments (
    id SERIAL PRIMARY KEY,
    post_id INT NOT NULL,
    parent_id INT,
    content TEXT NOT NULL CHECK (LENGTH(content) <= 2000),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_post
        FOREIGN KEY(post_id)
            REFERENCES posts(id)
            ON DELETE CASCADE,
    CONSTRAINT fk_parent
        FOREIGN KEY(parent_id)
            REFERENCES comments(id)
            ON DELETE CASCADE
);`)
	if err != nil {
		t.Fatalf("Unable to setup test database: %v\n", err)
	}

	return conn
}

func TestCreateComment(t *testing.T) {
	conn := setupTestDB(t)
	defer conn.Close(context.Background())

	repo := NewCommentsRepo(conn)

	post := &model2.Post{
		Title:           "Test Post",
		Content:         "This is a test post.",
		CommentsEnabled: true,
		CreatedAt:       time.Now(),
	}
	_, err := conn.Exec(context.Background(), `
		INSERT INTO posts (title, content, comments_enabled, created_at) VALUES ($1, $2, $3, $4)
	`, post.Title, post.Content, post.CommentsEnabled, post.CreatedAt)
	if err != nil {
		t.Fatalf("Unable to insert test post: %v\n", err)
	}

	comment := &model.Comment{
		PostID:  1,
		Content: "Test comment",
	}

	err = repo.CreateComment(comment)
	if err != nil {
		t.Errorf("Error creating comment: %v", err)
	}

	var createdComment model.Comment
	err = conn.QueryRow(context.Background(), `
		SELECT id, post_id, content FROM comments WHERE id = 1
	`).Scan(&createdComment.ID, &createdComment.PostID, &createdComment.Content)
	if err != nil {
		t.Fatalf("Unable to query created comment: %v\n", err)
	}

	if createdComment.Content != comment.Content {
		t.Errorf("Expected comment content '%s', got '%s'", comment.Content, createdComment.Content)
	}
}

func TestCreateReply(t *testing.T) {
	conn := setupTestDB(t)
	defer conn.Close(context.Background())

	repo := NewCommentsRepo(conn)

	post := &model2.Post{
		Title:           "Test Post",
		Content:         "This is a test post.",
		CommentsEnabled: true,
		CreatedAt:       time.Now(),
	}
	_, err := conn.Exec(context.Background(), `
		INSERT INTO posts (title, content, comments_enabled, created_at) VALUES ($1, $2, $3, $4)
	`, post.Title, post.Content, post.CommentsEnabled, post.CreatedAt)
	if err != nil {
		t.Fatalf("Unable to insert test post: %v\n", err)
	}

	comment := &model.Comment{
		PostID:  1,
		Content: "Test comment",
	}
	err = repo.CreateComment(comment)
	if err != nil {
		t.Fatalf("Error creating comment: %v", err)
	}

	reply := &model.Comment{
		PostID:  1,
		Content: "Test reply",
	}
	err = repo.CreateReply(comment.ID, reply)
	if err != nil {
		t.Errorf("Error creating reply: %v", err)
	}

	var createdReply model.Comment
	err = conn.QueryRow(context.Background(), `
		SELECT id, post_id, parent_id, content FROM comments WHERE id = $1
	`, reply.ID).Scan(&createdReply.ID, &createdReply.PostID, &createdReply.ParentID, &createdReply.Content)
	if err != nil {
		t.Fatalf("Unable to query created reply: %v\n", err)
	}

	if createdReply.Content != reply.Content {
		t.Errorf("Expected reply content '%s', got '%s'", reply.Content, createdReply.Content)
	}
	if createdReply.ParentID == nil || *createdReply.ParentID != comment.ID {
		t.Errorf("Expected parent ID %d, got %v", comment.ID, createdReply.ParentID)
	}
}

func TestGetComment(t *testing.T) {
	conn := setupTestDB(t)
	defer conn.Close(context.Background())

	repo := NewCommentsRepo(conn)

	post := &model2.Post{
		Title:           "Test Post",
		Content:         "This is a test post.",
		CommentsEnabled: true,
		CreatedAt:       time.Now(),
	}
	_, err := conn.Exec(context.Background(), `
		INSERT INTO posts (title, content, comments_enabled, created_at) VALUES ($1, $2, $3, $4)
	`, post.Title, post.Content, post.CommentsEnabled, post.CreatedAt)
	if err != nil {
		t.Fatalf("Unable to insert test post: %v\n", err)
	}

	comment := &model.Comment{
		PostID:  1,
		Content: "Test comment",
	}
	err = repo.CreateComment(comment)
	if err != nil {
		t.Fatalf("Error creating comment: %v", err)
	}

	retrievedComment, err := repo.GetComment(comment.ID)
	if err != nil {
		t.Errorf("Error retrieving comment: %v", err)
	}

	if retrievedComment.Content != comment.Content {
		t.Errorf("Expected comment content '%s', got '%s'", comment.Content, retrievedComment.Content)
	}
}

func TestGetAllComments(t *testing.T) {
	conn := setupTestDB(t)
	defer conn.Close(context.Background())

	repo := NewCommentsRepo(conn)

	post := &model2.Post{
		Title:           "Test Post",
		Content:         "This is a test post.",
		CommentsEnabled: true,
		CreatedAt:       time.Now(),
	}
	_, err := conn.Exec(context.Background(), `
		INSERT INTO posts (title, content, comments_enabled, created_at) VALUES ($1, $2, $3, $4)
	`, post.Title, post.Content, post.CommentsEnabled, post.CreatedAt)
	if err != nil {
		t.Fatalf("Unable to insert test post: %v\n", err)
	}

	comment1 := &model.Comment{
		PostID:  1,
		Content: "Test comment 1",
	}
	err = repo.CreateComment(comment1)
	if err != nil {
		t.Fatalf("Error creating comment 1: %v", err)
	}

	comment2 := &model.Comment{
		PostID:  1,
		Content: "Test comment 2",
	}
	err = repo.CreateComment(comment2)
	if err != nil {
		t.Fatalf("Error creating comment 2: %v", err)
	}

	comments, err := repo.GetAllComments()
	if err != nil {
		t.Errorf("Error retrieving all comments: %v", err)
	}

	if len(comments) != 2 {
		t.Errorf("Expected 2 comments, got %d", len(comments))
	}
}

func TestDeleteComment(t *testing.T) {
	conn := setupTestDB(t)
	defer conn.Close(context.Background())

	repo := NewCommentsRepo(conn)

	post := &model2.Post{
		Title:           "Test Post",
		Content:         "This is a test post.",
		CommentsEnabled: true,
		CreatedAt:       time.Now(),
	}
	_, err := conn.Exec(context.Background(), `
		INSERT INTO posts (title, content, comments_enabled, created_at) VALUES ($1, $2, $3, $4)
	`, post.Title, post.Content, post.CommentsEnabled, post.CreatedAt)
	if err != nil {
		t.Fatalf("Unable to insert test post: %v\n", err)
	}

	comment := &model.Comment{
		PostID:  1,
		Content: "Test comment",
	}
	err = repo.CreateComment(comment)
	if err != nil {
		t.Fatalf("Error creating comment: %v", err)
	}

	err = repo.DeleteComment(comment.ID)
	if err != nil {
		t.Errorf("Error deleting comment: %v", err)
	}

	_, err = repo.GetComment(comment.ID)
	if err == nil || err.Error() != "comment not found" {
		t.Errorf("Expected 'comment not found' error, got %v", err)
	}
}
